home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / misc / MD_ANet_Upload.lha / anet-upload / Move110.lha / Move / Move.c < prev    next >
C/C++ Source or Header  |  1994-03-10  |  31KB  |  1,302 lines

  1. /*
  2. Auto:        sc <file>
  3. Auto:        Protect Move P ADD
  4. */
  5.  
  6. /* $Revision Header built automatically *************** (do not edit) ************
  7. **
  8. ** © Copyright by GuntherSoft
  9. **
  10. ** File             : SnakeSYS:CPrgs/Utils/Move.c
  11. ** Created on       : Wednesday, 11.08.93 15:01:14
  12. ** Created by       : Kai Iske
  13. ** Current revision : V1.10
  14. **
  15. **
  16. ** Purpose
  17. ** -------
  18. **   - Small move utility which supports wildcards and doesn`t use
  19. **     Rename() nor Copy() nor anything similar...
  20. **
  21. ** Revision V1.10
  22. ** --------------
  23. ** created on Sunday, 06.03.94 16:57:29  by  Kai Iske.   LogMessage :
  24. **  -*-  created on Sunday, 06.03.94 16:57:29  by  Kai Iske.   LogMessage :
  25. **   - Move didn`t end up some operations with a "moved" string,
  26. **     thus leading to corrupted display
  27. **     (Reported by : Albert-Jan Brouwer)
  28. **   - One still couldn`t rename a directory
  29. **     (Reported by : Albert-Jan Brouwer)
  30. **
  31. ** Revision V1.9
  32. ** --------------
  33. ** created on Saturday, 26.02.94 14:15:24  by  Kai Iske.   LogMessage :
  34. **  -*-  changed on Saturday, 26.02.94 14:29:20  by  Kai Iske.   LogMessage :
  35. **   - On recursive moves, Move will indent the output according to
  36. **     recursion depth. This is for better readability
  37. **  -*-  changed on Saturday, 26.02.94 14:19:22  by  Kai Iske.   LogMessage :
  38. **   - Move will refuse to move a dir to itself now.
  39. **  -*-  created on Saturday, 26.02.94 14:15:24  by  Kai Iske.   LogMessage :
  40. **   - One couldn`t move a dir to another dir on the same device
  41. **
  42. ** Revision V1.8
  43. ** --------------
  44. ** created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  45. **  -*-  changed on Sunday, 19.12.93 01:47:54  by  Kai Iske.   LogMessage :
  46. **   - Added PURE information to Doc, since Move really is pure
  47. **     (Suggested by : Albert-Jan Brouver)
  48. **  -*-  changed on Sunday, 19.12.93 01:46:23  by  Kai Iske.   LogMessage :
  49. **   - Due to the move-renaming bug one couldn`t rename a dir
  50. **     an Assign was put on.
  51. **     (Reported by : Albert-Jan Brouver)
  52. **  -*-  created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  53. **   - Fixed move-renaming of directories.
  54. **     (Reported by : Albert-Jan Brouver)
  55. **   - Move had some severe problems recursively moving
  56. **     the contents of a directory
  57. **
  58. ** Revision V1.7
  59. ** --------------
  60. ** created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  61. **  -*-  changed on Saturday, 04.12.93 23:26:25  by  Kai Iske.   LogMessage :
  62. **   - Error while moving to a "device full" disk
  63. **     (Reported by : Chris Conger)
  64. **  -*-  created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  65. **   - FileName length-bug fixed
  66. **     (Reported by : Juergen Lang)
  67. **   - Recompiled using SAS 6.50
  68. **   - Stack usage reduced
  69. **
  70. ** Revision V1.6
  71. ** --------------
  72. ** created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  73. **  -*-  changed on Saturday, 16.10.93 15:17:29  by  Kai Iske.   LogMessage :
  74. **   - Move got screwed up, when attempting to move a
  75. **     zero size file
  76. **  -*-  changed on Friday, 15.10.93 16:03:35  by  Kai Iske.   LogMessage :
  77. **   - Added Buffer Keyword to specify the maximum buffer
  78. **     size for an inter device move. Normally Move would have used
  79. **     the max amount of available free memory in order to
  80. **     accomplish the move, or the size needed by the file...
  81. **     (Suggested by : Christof Damian)
  82. **  -*-  created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  83. **   - One couldn`t rename a file using move, because the
  84. **     "destination" file was removed before doing the rename,
  85. **     ie. the source file was deleted.
  86. **     (Reported by : Chris Conger)
  87. **
  88. ** Revision V1.5
  89. ** --------------
  90. ** created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  91. **  -*-  changed on Tuesday, 05.10.93 02:03:22  by  Kai Iske.   LogMessage :
  92. **   - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment
  93. **     etc. This lead to MungWall hits (of course it did)
  94. **     (Reported by Nico Francois)
  95. **  -*-  created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  96. **   - Exidentially called one ExAll() without ED_SIZE
  97. **     This lead to some calls to DoTheMove without the Size set ;)
  98. **     (Reported by  Karsten Weiss)
  99. **
  100. ** Revision V1.4
  101. ** --------------
  102. ** created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  103. **  -*-  created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  104. **   - Now uses Rename() when source and dest are on the same
  105. **     device. This is faster ;) Why haven`t I thought of that
  106. **     earlier ??? ;)
  107. **
  108. ** Revision V1.3
  109. ** --------------
  110. ** created on Wednesday, 25.08.93 16:32:43  by  Kai Iske.   LogMessage :
  111. **   - UnLock Problem solved when doing recursive Dir-Moves
  112. **     This bug lead to "Object in use" error messages
  113. **
  114. ** Revision V1.2
  115. ** --------------
  116. ** created on Tuesday, 17.08.93 22:48:38  by  Kai Iske.   LogMessage :
  117. **   - Added CTRL-C checking
  118. **   - Added FORCE Flag in order to move read/deleteprotected or
  119. **     to overwrite a delete/writeprotected files
  120. **
  121. ** Revision V1.1
  122. ** --------------
  123. ** created on Monday, 16.08.93 22:53:34  by  Kai Iske.   LogMessage :
  124. **   - Added well known CLONE, DATES, COM, NOPRO,
  125. **     QUIET and NOREQ options also used by e.g. Rename
  126. **
  127. ** Revision V1.0
  128. ** --------------
  129. ** created on Wednesday, 11.08.93 15:01:14  by  Kai Iske.   LogMessage :
  130. **     --- Initial release ---
  131. **
  132. *********************************************************************************/
  133. #define REVISION "1.10"
  134. #define REVDATE  "10.03.94"
  135. #define REVTIME  "00:19:06"
  136. #define AUTHOR   "Kai Iske"
  137. #define VERNUM   1
  138. #define REVNUM   10
  139.  
  140. #include    <string.h>
  141. #include    <stdlib.h>
  142. #include    <exec/types.h>
  143. #include    <proto/exec.h>
  144. #include    <proto/dos.h>
  145. #include    <exec/memory.h>
  146. #include    <exec/execbase.h>
  147. #include    <dos/exall.h>
  148. #include    <dos/dos.h>
  149. #include    <dos/dosextens.h>
  150.  
  151.  
  152.  
  153.  
  154. /**********************************************************************/
  155. /*                         Defines for Flags                          */
  156. /**********************************************************************/
  157. #define    CLONE        0x0001
  158. #define    DATES        0x0002
  159. #define    NOPRO        0x0004
  160. #define    COM        0x0008
  161. #define    QUIET        0x0010
  162. #define    FORCE        0x0020
  163.  
  164. #define    WATCHSIGS    SIGBREAKF_CTRL_C
  165.  
  166.  
  167.  
  168. /**********************************************************************/
  169. /*                      Static char definitions                       */
  170. /**********************************************************************/
  171. static    const char    *Version    = "$VER: Move "REVISION" ("REVDATE")\0";
  172. static    const char    *Template    = "FROM/M,TO/A,CLONE/S,DATES/S,NOPRO/S,COM/S,QUIET/S,NOREQ/S,FORCE/S,BUFFER/N/K";
  173. enum    {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, BUFFER_ARG, LAST_ARG};
  174.  
  175.  
  176.  
  177. /**********************************************************************/
  178. /*                             Prototypes                             */
  179. /**********************************************************************/
  180. int    __saveds DoMove(void);
  181. BOOL    __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, ULONG RecDepth);
  182. BOOL    __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer);
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189. /**********************************************************************/
  190. /*                          The main program                          */
  191. /**********************************************************************/
  192. int __saveds DoMove(void)
  193. {
  194.     struct    FileInfoBlock    *FIB;
  195.     struct    ExecBase    *SysBase = *((struct ExecBase **)0x4L);
  196.     struct    DOSBase        *DOSBase;
  197.     struct    Process        *MyProc = (struct Process *)SysBase->ThisTask;
  198.     struct    RDArgs        *RDArgs;
  199.     struct    ExAllControl    *EAC;
  200.     struct    ExAllData    *EAB, *EAD;
  201.     APTR    *Args,
  202.         *OldWindow;
  203.     BPTR    DirLock,
  204.         OutHandle;
  205.     char    **FromPtr;
  206.     char    *ToPtr;
  207.     char    *Pattern;
  208.     char    *PathName    = NULL;
  209.     char    *Buffer        = NULL;
  210.     LONG    HitMask;
  211.     UWORD    NumFrom        = 0,
  212.         PatternType,
  213.         CopyFlags    = 0;
  214.     ULONG    MaxBuffer    = 0;
  215.     BOOL    PatternFrom,
  216.         GoOn        = FALSE,
  217.         Scanning;
  218.  
  219.  
  220.  
  221.  
  222.         // Ignore startup from WB
  223.  
  224.     if(!(MyProc->pr_CLI))
  225.     {
  226.         struct    Message    *MyMsg;
  227.  
  228.         WaitPort(&MyProc->pr_MsgPort);
  229.         MyMsg = GetMsg(&MyProc->pr_MsgPort);
  230.         Disable();
  231.         ReplyMsg(MyMsg);
  232.         return(10);
  233.     }
  234.  
  235.         // Do the wild thing
  236.  
  237.     if((DOSBase = (struct DOSBase *)OpenLibrary("dos.library", 37)))
  238.     {
  239.             // Allocate buffers
  240.  
  241.         if((Pattern = AllocVec(1024, MEMF_CLEAR)) && (PathName = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)))
  242.         {
  243.             if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  244.             {
  245.                     // Get buffer for ReadArgs()
  246.  
  247.                 if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
  248.                 {
  249.                         // Get structure for ExAll()
  250.  
  251.                     if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  252.                     {
  253.                             // Get buffer for ExAll()
  254.  
  255.                         if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR)))
  256.                         {
  257.                                 // Parse commandline
  258.  
  259.                             if((RDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL)))
  260.                             {
  261.                                     // From and to really there ??
  262.  
  263.                                 if(Args[FROM_ARG] && Args[TO_ARG])
  264.                                 {
  265.                                         // A O.K. so far
  266.  
  267.                                     GoOn        = TRUE;
  268.  
  269.                                         // Get output handle
  270.  
  271.                                     OutHandle    = Output();
  272.  
  273.                                         // Get Flags
  274.  
  275.                                     if(Args[CLONE_ARG])
  276.                                         CopyFlags    |=    CLONE;
  277.                                     if(Args[DATES_ARG])
  278.                                         CopyFlags    |=    DATES;
  279.                                     if(Args[NOPRO_ARG])
  280.                                         CopyFlags    |=    NOPRO;
  281.                                     if(Args[COM_ARG])
  282.                                         CopyFlags    |=    COM;
  283.                                     if(Args[QUIET_ARG])
  284.                                         CopyFlags    |=    QUIET;
  285.                                     if(Args[FORCE_ARG])
  286.                                         CopyFlags    |=    FORCE;
  287.                                     if(Args[BUFFER_ARG])
  288.                                         MaxBuffer    =    *((ULONG *)Args[BUFFER_ARG]) * 1024;
  289.  
  290.                                         // Check for NOREQ Option
  291.  
  292.                                     if(Args[NOREQ_ARG])
  293.                                     {
  294.                                         OldWindow        = MyProc->pr_WindowPtr;
  295.                                         MyProc->pr_WindowPtr    = (void *)(-1L);
  296.                                     }
  297.  
  298.                                         // Get pointers to Files
  299.  
  300.                                     FromPtr    = (char **)Args[FROM_ARG];
  301.                                     ToPtr    = (char *)Args[TO_ARG];
  302.  
  303.                                         // Count FROM entries
  304.  
  305.                                     while(*FromPtr++)
  306.                                         NumFrom++;
  307.  
  308.                                         // Restore FromPtr
  309.  
  310.                                     FromPtr    = (char **)Args[FROM_ARG];
  311.  
  312.                                         // Set pattern if there are more than 1
  313.                                         // FROM files or if the only FROM file
  314.                                         // is a pattern
  315.  
  316.                                     if(NumFrom > 1)
  317.                                         PatternFrom = TRUE;
  318.                                     else
  319.                                         PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 1024);
  320.  
  321.                                         // If a pattern is used, check
  322.                                         // whether the dest really is a dir
  323.  
  324.                                     if(PatternFrom)
  325.                                     {
  326.                                             // Try to obtain a lock
  327.  
  328.                                         if((DirLock = Lock(ToPtr, ACCESS_READ)))
  329.                                         {
  330.                                                 // Check file
  331.  
  332.                                             if(Examine(DirLock, FIB))
  333.                                             {
  334.                                                     // Get type of destination entry
  335.  
  336.                                                 GoOn = (FIB->fib_DirEntryType >= 0);
  337.  
  338.                                                     // If it`s not a directory (multiple files are to be moved)
  339.                                                     // issue an error
  340.  
  341.                                                 if(!GoOn)
  342.                                                     FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n");
  343.                                             }
  344.                                             else
  345.                                             {
  346.                                                     // Examine() failed -> Abort
  347.  
  348.                                                 GoOn = FALSE;
  349.                                                 PrintFault(IoErr(), "\nMove ");
  350.                                             }
  351.  
  352.                                                 // Unlock CheckDir
  353.  
  354.                                             UnLock(DirLock);
  355.                                         }
  356.                                         else
  357.                                         {
  358.                                                 // If lock failed issue an error
  359.  
  360.                                             PrintFault(IoErr(), "\nMove ");
  361.                                             GoOn = FALSE;
  362.                                         }
  363.                                     }
  364.  
  365.  
  366.  
  367.                                         // Loop for all source files
  368.  
  369.                                     while(NumFrom && GoOn)
  370.                                     {
  371.                                             // Check for CTRL-C
  372.  
  373.                                         if(GoOn)
  374.                                             HitMask    = CheckSignal(WATCHSIGS);
  375.  
  376.                                         if(!HitMask && GoOn)
  377.                                         {
  378.                                                 // Check if this source is a pattern
  379.  
  380.                                             strcpy(Buffer, FilePart(*FromPtr));
  381.                                             strupr(Buffer);
  382.                                             PatternType = ParsePatternNoCase(Buffer, Pattern, 1024);
  383.  
  384.                                                 // It is a pattern
  385.  
  386.                                             if(PatternType == 1)
  387.                                             {
  388.                                                     // Create name of source
  389.  
  390.                                                 strcpy(Buffer, *FromPtr);
  391.                                                 *PathPart(Buffer)    = '\0';
  392.  
  393.                                                     // Get Lock for Source - Directory
  394.  
  395.                                                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  396.                                                 {
  397.                                                         // Setup ExAllControl-Structure
  398.  
  399.                                                     EAC->eac_LastKey    = 0L;
  400.                                                     EAC->eac_MatchString    = Pattern;
  401.                                                     EAC->eac_MatchFunc    = NULL;
  402.  
  403.                                                     do
  404.                                                     {
  405.                                                             // Check for CTRL-C
  406.  
  407.                                                         if(GoOn)
  408.                                                             HitMask = CheckSignal(WATCHSIGS);
  409.  
  410.                                                         if(HitMask)
  411.                                                             GoOn = FALSE;
  412.  
  413.                                                             // Scan directory
  414.  
  415.                                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  416.  
  417.                                                             // Issue Error
  418.  
  419.                                                         if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  420.                                                         {
  421.                                                             PrintFault(IoErr(), "\nMove ");
  422.                                                             GoOn = FALSE;
  423.                                                         }
  424.  
  425.                                                             // End of Dir reached
  426.  
  427.                                                         if(EAC->eac_Entries == 0)
  428.                                                             Scanning = FALSE;
  429.                                                         else if(GoOn)
  430.                                                         {
  431.                                                             EAD    = EAB;
  432.  
  433.                                                             do
  434.                                                             {
  435.                                                                     // Check for CTRL-C
  436.  
  437.                                                                 if(GoOn)
  438.                                                                     HitMask = CheckSignal(WATCHSIGS);
  439.  
  440.                                                                 if(!HitMask && GoOn)
  441.                                                                 {
  442.                                                                         // Create filename for this file to be moved
  443.  
  444.                                                                     strcpy(PathName, *FromPtr);
  445.                                                                     *PathPart(PathName)    = '\0';
  446.                                                                     AddPart(PathName, EAD->ed_Name, 1024);
  447.  
  448.                                                                         // Move file
  449.  
  450.                                                                     GoOn    = DoTheMove(PathName, ToPtr, TRUE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask, MaxBuffer, 1);
  451.  
  452.                                                                     EAD    = EAD->ed_Next;
  453.                                                                 }
  454.                                                                 else
  455.                                                                     GoOn = FALSE;
  456.  
  457.                                                             } while(EAD && GoOn);
  458.                                                         }
  459.                                                     } while(Scanning);
  460.  
  461.                                                         // Unlock source directory
  462.  
  463.                                                     UnLock(DirLock);
  464.                                                 }
  465.                                                 else
  466.                                                 {
  467.                                                         // Issue error, if dir could not be locked
  468.  
  469.                                                     PrintFault(IoErr(), "\nMove ");
  470.                                                     GoOn    = FALSE;
  471.                                                 }
  472.                                             }
  473.                                                 // No pattern
  474.  
  475.                                             else if(PatternType == 0)
  476.                                             {
  477.                                                     // Try to lock source file/dir
  478.  
  479.                                                 if((DirLock = Lock(*FromPtr, ACCESS_READ)))
  480.                                                 {
  481.                                                         // Examine this lock
  482.  
  483.                                                     if(Examine(DirLock, FIB))
  484.                                                     {
  485.                                                             // Unlock directory and do the move
  486.  
  487.                                                         UnLock(DirLock);
  488.                                                         GoOn    = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, DOSBase, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask, MaxBuffer, 1);
  489.                                                     }
  490.                                                     else
  491.                                                     {
  492.                                                             // Issue error on failed Examine()
  493.  
  494.                                                         PrintFault(IoErr(), "\nMove ");
  495.                                                         GoOn = FALSE;
  496.                                                         UnLock(DirLock);
  497.                                                     }
  498.                                                 }
  499.                                                 else
  500.                                                 {
  501.                                                         // No Lock() no more moves
  502.  
  503.                                                     PrintFault(IoErr(), "\nMove ");
  504.                                                     GoOn = FALSE;
  505.                                                 }
  506.                                             }
  507.  
  508.                                                 // Error condition
  509.  
  510.                                             else
  511.                                             {
  512.                                                 PrintFault(IoErr(), "\nMove ");
  513.                                                 GoOn = FALSE;
  514.                                             }
  515.  
  516.                                             NumFrom--;
  517.                                             FromPtr++;
  518.                                         }
  519.                                         else
  520.                                             GoOn    = FALSE;
  521.                                     }
  522.                                 }
  523.  
  524.                                     // Free ReadArgs
  525.  
  526.                                 FreeArgs(RDArgs);
  527.                             }
  528.                             else
  529.                                 PrintFault(IoErr(), "\nMove ");
  530.  
  531.                                 // Free ExAll-Buffer
  532.  
  533.                             FreeVec(EAB);
  534.                         }
  535.                         else
  536.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  537.  
  538.                             // Free ExAllControl Structure
  539.  
  540.                         FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);
  541.                     }
  542.                     else
  543.                         PrintFault(IoErr(), "\nMove ");
  544.  
  545.                         // Free Argument Buffer
  546.  
  547.                     FreeVec(Args);
  548.                 }
  549.                 else
  550.                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  551.  
  552.                 FreeVec(FIB);
  553.             }
  554.             else
  555.                 PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  556.         }
  557.         else
  558.             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  559.  
  560.  
  561.             // Free allocated buffers
  562.  
  563.         if(Pattern)
  564.             FreeVec(Pattern);
  565.  
  566.         if(PathName)
  567.             FreeVec(PathName);
  568.  
  569.         if(Buffer)
  570.             FreeVec(Buffer);
  571.  
  572.  
  573.             // Check for Abort-Signals
  574.  
  575.         if(HitMask && !(CopyFlags & QUIET))
  576.         {
  577.                 // Display appropriate message
  578.  
  579.             if(HitMask & SIGBREAKF_CTRL_C)
  580.                 FPuts(OutHandle, "\nMove ^C...\n");
  581.         }
  582.  
  583.             // Close DOSLibrary
  584.  
  585.         CloseLibrary((struct Library *)DOSBase);
  586.     }
  587.  
  588.         // Restore old window pointer (if any)
  589.  
  590.     if(OldWindow)
  591.         MyProc->pr_WindowPtr    = OldWindow;
  592.  
  593.  
  594.         // Depending on this flag return appropriate return code
  595.  
  596.     if(GoOn)
  597.         return(0);
  598.     else
  599.         return(10);
  600. }
  601.  
  602.  
  603.  
  604.  
  605. /**********************************************************************/
  606. /*                            Do the move                             */
  607. /**********************************************************************/
  608. BOOL __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, ULONG RecDepth)
  609. {
  610.     struct    ExAllControl    *EAC;
  611.     struct    ExAllData    *EAB, *EAD;
  612.     struct    DevProc        *FromDev, *ToDev;
  613.     char    *NewDir;
  614.     char    *Buffer        = NULL;
  615.     char    *ToDir        = NULL;
  616.     char    *DispBuff    = NULL;
  617.     UWORD    Len;
  618.     BPTR    DirLock;
  619.     BOOL    RetVal        = TRUE,
  620.         Scanning,
  621.         DoRename    = FALSE,
  622.         MoveDirToSame    = FALSE;
  623.  
  624.  
  625.         // Try to allocate buffers
  626.  
  627.     if((NewDir = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)) && (ToDir = AllocVec(1024, MEMF_CLEAR)) && (DispBuff = AllocVec(1024, MEMF_CLEAR)))
  628.     {
  629.             // Is it a directory ???
  630.             // If yes, recursively loop for all entries within dir
  631.  
  632.         if(Type >= 0)
  633.         {
  634.             strcpy(Buffer, FromFile);
  635.  
  636.                 // Get length of from name
  637.  
  638.             Len    = strlen(Buffer);
  639.  
  640.                 // Really got a from name ?!?
  641.  
  642.             if(Len)
  643.             {
  644.                 if(Buffer[Len - 1] == '/')
  645.                     Buffer[Len - 1] = '\0';
  646.  
  647.                     // Copy dest name to buffer
  648.  
  649.                 strcpy(NewDir, ToPath);
  650.  
  651.                     // Check whether dest dir is on same device
  652.                     // If so, do a simple rename
  653.  
  654.                 FromDev    = GetDeviceProc(Buffer, NULL);
  655.                 ToDev    = GetDeviceProc(NewDir, NULL);
  656.  
  657.                     // If the same device is used -> Do the rename
  658.  
  659.                 if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
  660.                     DoRename    = TRUE;
  661.  
  662.                 if(FromDev)
  663.                     FreeDeviceProc(FromDev);
  664.  
  665.                 if(ToDev)
  666.                     FreeDeviceProc(ToDev);
  667.  
  668.  
  669.                     // Check for dir moving to itself...
  670.  
  671.                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  672.                 {
  673.                     BPTR    TestLock;
  674.  
  675.                     if((TestLock = Lock(NewDir, ACCESS_READ)))
  676.                     {
  677.                             // Renaming a directory ???
  678.  
  679.                         if(((struct FileLock *)BADDR(DirLock))->fl_Key == ((struct FileLock *)BADDR(TestLock))->fl_Key)
  680.                             MoveDirToSame = TRUE;
  681.  
  682.                         UnLock(TestLock);
  683.                     }
  684.  
  685.                     UnLock(DirLock);
  686.                 }
  687.  
  688.  
  689.                     // Ok, we are to move
  690.                     // If a pattern is used print the name of the dir to be moved
  691.  
  692.                 if(PatternFrom && !(CopyFlags & QUIET))
  693.                 {
  694.                     int    i;
  695.  
  696.                         // Prepend number of spaces according to recursion depth
  697.  
  698.                     for(i = 0; i < RecDepth; i++)
  699.                         DispBuff[i]    = ' ';
  700.                     DispBuff[i]    = '\0';
  701.  
  702.                     strcat(DispBuff, FromFile);
  703.                     strcat(DispBuff, "...");
  704.                     Write(OutHandle, " ", 1);
  705.                     Write(OutHandle, DispBuff, strlen(DispBuff));
  706.                 }
  707.  
  708.  
  709.                     // Destination directory available ???
  710.                     // If so, we are to move to that directory
  711.                     // Otherwise, we`ll simply rename
  712.  
  713.                 if((DirLock = Lock(NewDir, ACCESS_READ)))
  714.                 {
  715.                     UnLock(DirLock);
  716.  
  717.                         // Add name of from directory
  718.  
  719.                     if(!MoveDirToSame)
  720.                         AddPart(NewDir, FilePart(Buffer), 1024);
  721.                 }
  722.  
  723.  
  724.                     // Simple rename; no cross-device move ?!?
  725.  
  726.                 if(DoRename)
  727.                 {
  728.                         // Do the rename
  729.  
  730.                     if(!Rename(Buffer, NewDir))
  731.                     {
  732.                         PrintFault(IoErr(), "\nMove ");
  733.                         RetVal = FALSE;
  734.                     }
  735.                 }
  736.                 else
  737.                 {
  738.                         // Clone directory name of source
  739.  
  740.                     strcpy(ToDir, Buffer);
  741.  
  742.                         // Try to lock directory or
  743.                         // create it, if not existent
  744.  
  745.                     if(!(DirLock = Lock(NewDir, ACCESS_READ)))
  746.                     {
  747.                         if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET))
  748.                             Write(OutHandle, " [created]...", 13);
  749.                     }
  750.  
  751.                         // Now end the directory move string with a RETURN
  752.  
  753.                     Write(OutHandle, "\n", 1);
  754.  
  755.                         // Got the destination directory ???
  756.  
  757.                     if(DirLock)
  758.                     {
  759.                             // Unlock Directory
  760.  
  761.                         UnLock(DirLock);
  762.  
  763.                             // Lock sourcedirectory
  764.  
  765.                         if((DirLock = Lock(Buffer, ACCESS_READ)))
  766.                         {
  767.                                 // Get ExAll Control for recursive directory search
  768.  
  769.                             if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  770.                             {
  771.                                     // Allocate buffer for move
  772.  
  773.                                 if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR)))
  774.                                 {
  775.                                     EAC->eac_LastKey    = 0L;
  776.                                     EAC->eac_MatchString    = NULL;
  777.                                     EAC->eac_MatchFunc    = NULL;
  778.  
  779.                                     do
  780.                                     {
  781.                                             // Check for CTRL-C
  782.  
  783.                                         if(RetVal)
  784.                                             (*HitMask) = CheckSignal(WATCHSIGS);
  785.  
  786.                                         if((*HitMask))
  787.                                             RetVal = FALSE;
  788.  
  789.                                             // Scan directory for entries
  790.  
  791.                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  792.  
  793.                                             // Check for an error
  794.  
  795.                                         if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  796.                                         {
  797.                                             PrintFault(IoErr(), "\nMove ");
  798.                                             RetVal = FALSE;
  799.                                         }
  800.  
  801.                                             // End of Dir reached
  802.  
  803.                                         if(EAC->eac_Entries == 0)
  804.                                             Scanning = FALSE;
  805.                                         else if(RetVal)
  806.                                         {
  807.                                             EAD = EAB;
  808.  
  809.                                             do
  810.                                             {
  811.                                                     // Check for CTRL-C
  812.  
  813.                                                 if(RetVal)
  814.                                                     (*HitMask) = CheckSignal(WATCHSIGS);
  815.  
  816.                                                 if(!(*HitMask) && RetVal)
  817.                                                 {
  818.                                                         // Create filename of source
  819.  
  820.                                                     strcpy(Buffer, FromFile);
  821.                                                     AddPart(Buffer, EAD->ed_Name, 1024);
  822.  
  823.                                                         // And start recursion
  824.  
  825.                                                     RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask, MaxBuffer, RecDepth + 1);
  826.  
  827.                                                         // Loop for all entries
  828.  
  829.                                                     EAD = EAD->ed_Next;
  830.                                                 }
  831.                                                 else
  832.                                                     RetVal = FALSE;
  833.  
  834.                                             } while(EAD && RetVal);
  835.                                         }
  836.                                     } while(Scanning);
  837.  
  838.                                         // Free ExAll Buffer
  839.  
  840.                                     FreeVec(EAB);
  841.                                 }
  842.                                 else
  843.                                 {
  844.                                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  845.                                     RetVal = FALSE;
  846.                                 }
  847.  
  848.                                     // Free ExAllControl Structure
  849.  
  850.                                 FreeDosObject(DOS_EXALLCONTROL, EAC);
  851.                             }
  852.                             else
  853.                             {
  854.                                 PrintFault(IoErr(), "\nMove ");
  855.                                 RetVal = FALSE;
  856.                             }
  857.  
  858.                             UnLock(DirLock);
  859.                         }
  860.                         else
  861.                         {
  862.                             PrintFault(IoErr(), "\nMove ");
  863.                             RetVal = FALSE;
  864.                         }
  865.                     }
  866.                     else
  867.                     {
  868.                         PrintFault(IoErr(), "\nMove ");
  869.                         RetVal = FALSE;
  870.                     }
  871.                 }
  872.  
  873.                     // Ok, this dir was moved (no rename), so remove it
  874.  
  875.                 if(RetVal && !DoRename)
  876.                 {
  877.                         // With force mode set on,
  878.                         // First make dir deletable
  879.  
  880.                     if(CopyFlags & FORCE)
  881.                         SetProtection(ToDir, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  882.  
  883.                         // Delete directory
  884.  
  885.                     if(!DeleteFile(ToDir))
  886.                     {
  887.                         PrintFault(IoErr(), "\nMove ");
  888.                         RetVal = FALSE;
  889.                     }
  890.                 }
  891.  
  892.                     // Display "moved" message
  893.  
  894.                 if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  895.                     FPuts(OutHandle, " moved\n");
  896.             }
  897.         }
  898.         else
  899.         {
  900.                 // Ok, we are to move
  901.                 // If a pattern is used print the name of the file to be moved
  902.  
  903.             if(PatternFrom && !(CopyFlags & QUIET))
  904.             {
  905.                 int    i;
  906.  
  907.                     // Prepend number of spaces according to recursion depth
  908.  
  909.                 for(i = 0; i < RecDepth; i++)
  910.                     DispBuff[i]    = ' ';
  911.                 DispBuff[i]    = '\0';
  912.  
  913.                 strcat(DispBuff, FromFile);
  914.                 strcat(DispBuff, "...");
  915.                 Write(OutHandle, " ", 1);
  916.                 Write(OutHandle, DispBuff, strlen(DispBuff));
  917.             }
  918.  
  919.                 // On a plain file -> Simply move it
  920.  
  921.             RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, DOSBase, Size, CopyFlags, HitMask, MaxBuffer);
  922.  
  923.                 // If there was a pattern (or a single directory)
  924.                 // end the Move string
  925.  
  926.             if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  927.                 FPuts(OutHandle, " moved\n");
  928.         }
  929.     }
  930.     else
  931.     {
  932.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  933.         RetVal = FALSE;
  934.     }
  935.  
  936.         // De-Allocate buffers
  937.  
  938.     if(NewDir)
  939.         FreeVec(NewDir);
  940.  
  941.     if(Buffer)
  942.         FreeVec(Buffer);
  943.  
  944.     if(ToDir)
  945.         FreeVec(ToDir);
  946.  
  947.     if(DispBuff)
  948.         FreeVec(DispBuff);
  949.  
  950.         // Return Code
  951.  
  952.     return(RetVal);
  953. }
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962. /**********************************************************************/
  963. /*                       Physically move a file                       */
  964. /**********************************************************************/
  965. BOOL __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer)
  966. {
  967.     struct    FileInfoBlock    *FIB;
  968.     struct    DevProc        *FromDev, *ToDev;
  969.     BPTR    InFile, OutFile;
  970.     APTR    CopyBuffer;
  971.     char    *DestName;
  972.     ULONG    AvailSize,
  973.         ReadSize;
  974.     LONG    InKey        = -1,
  975.         OutKey        = -1;
  976.     BOOL    RetVal        = TRUE,
  977.         ErrCpy        = FALSE,
  978.         LoopCpy        = TRUE,
  979.         DoRename    = FALSE,
  980.         RemoveFirst    = FALSE;
  981.  
  982.  
  983.         // Allocate buffer for Destination name
  984.  
  985.     if(!(DestName = AllocVec(1024, MEMF_CLEAR)))
  986.     {
  987.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  988.         return(FALSE);
  989.     }
  990.  
  991.     if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  992.     {
  993.  
  994.         strcpy(DestName, ToPath);
  995.  
  996.             // Check, if destfile already exists
  997.             // If so, check if it`s a dir.
  998.             // Yes -> Copy with sourcename
  999.             // No -> Copy with given name
  1000.  
  1001.         if((OutFile = Lock(DestName, ACCESS_READ)))
  1002.         {
  1003.             if(Examine(OutFile, FIB))
  1004.             {
  1005.                     // If dest is a directory move with source name
  1006.  
  1007.                 if(FIB->fib_DirEntryType >= 0)
  1008.                     AddPart(DestName, FilePart(FromFile), 1024);
  1009.                 else
  1010.                 {
  1011.                     OutKey        = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  1012.                     RemoveFirst    = TRUE;
  1013.                 }
  1014.             }
  1015.             else
  1016.             {
  1017.                     // No examine -> Use source filename
  1018.  
  1019.                 AddPart(DestName, FilePart(FromFile), 1024);
  1020.             }
  1021.  
  1022.             UnLock(OutFile);
  1023.         }
  1024.  
  1025.             // Try to lock input file
  1026.  
  1027.         if((InFile = Lock(FromFile, ACCESS_READ)))
  1028.         {
  1029.                 // Get DiskBlock for inputfile
  1030.  
  1031.             InKey    = ((struct FileLock *)BADDR(InFile))->fl_Key;
  1032.  
  1033.                 // Get old protection bits, comment and filedate
  1034.  
  1035.             if(Examine(InFile, FIB))
  1036.             {
  1037.                     // In Force mode -> Force read and delete permissons
  1038.                     // for input file
  1039.  
  1040.                 if(CopyFlags & FORCE)
  1041.                     SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE));
  1042.             }
  1043.             else
  1044.             {
  1045.                 PrintFault(IoErr(), "\nMove ");
  1046.                 RetVal = FALSE;
  1047.             }
  1048.  
  1049.                 // If so, unlock
  1050.  
  1051.             UnLock(InFile);
  1052.         }
  1053.         else
  1054.         {
  1055.             PrintFault(IoErr(), "\nMove ");
  1056.             RetVal = FALSE;
  1057.         }
  1058.  
  1059.  
  1060.             // Check whether to use a Rename() or a real Copy-Mode
  1061.  
  1062.         FromDev    = GetDeviceProc(FromFile, NULL);
  1063.         ToDev    = GetDeviceProc(DestName, NULL);
  1064.  
  1065.             // If the same device is used -> Do the rename
  1066.  
  1067.         if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
  1068.             DoRename = TRUE;
  1069.  
  1070.         if(FromDev)
  1071.             FreeDeviceProc(FromDev);
  1072.  
  1073.         if(ToDev)
  1074.             FreeDeviceProc(ToDev);
  1075.  
  1076.  
  1077.             // No Rename -> Do the right move ;)
  1078.  
  1079.         if(!DoRename)
  1080.         {
  1081.                 // Open Input file
  1082.  
  1083.             if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE)))
  1084.             {
  1085.                     // Outfile already there ??? and in force mode ???
  1086.  
  1087.                 if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ))))
  1088.                 {
  1089.                         // Force delete and write permissons
  1090.  
  1091.                     UnLock(OutFile);
  1092.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  1093.                 }
  1094.  
  1095.                     // Open Output file
  1096.  
  1097.                 if((OutFile = Open(DestName, MODE_NEWFILE)))
  1098.                 {
  1099.                         // Is there any data within the file ???
  1100.  
  1101.                     if(Size)
  1102.                     {
  1103.                             // Get available size of memory
  1104.                             // or take the user`s buffer size into account
  1105.  
  1106.                         AvailSize    = (MaxBuffer != 0) ? MaxBuffer : (AvailMem(MEMF_LARGEST) - 102400);
  1107.                         Size        = (Size > AvailSize) ? AvailSize : Size;
  1108.  
  1109.                             // Loop till we get a buffer
  1110.  
  1111.                         while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR)))
  1112.                             Size    -= 1024;
  1113.  
  1114.                         if(CopyBuffer)
  1115.                         {
  1116.                                 // Loop for portions of the source file
  1117.  
  1118.                             while(RetVal && LoopCpy)
  1119.                             {
  1120.                                     // Check for CTRL-C
  1121.  
  1122.                                 if(RetVal)
  1123.                                     (*HitMask) = CheckSignal(WATCHSIGS);
  1124.  
  1125.                                 if(!(*HitMask) && RetVal)
  1126.                                 {
  1127.                                         // Read part of file
  1128.  
  1129.                                     if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0)
  1130.                                     {
  1131.                                             // And write it back
  1132.  
  1133.                                         if(Write(OutFile, CopyBuffer, ReadSize) == -1)
  1134.                                         {
  1135.                                             PrintFault(IoErr(), "\nMove ");
  1136.                                             RetVal    = FALSE;
  1137.                                             ErrCpy    = TRUE;
  1138.                                         }
  1139.                                     }
  1140.                                     else
  1141.                                     {
  1142.                                             // EOF ??? -> End copy
  1143.  
  1144.                                         if(ReadSize == 0)
  1145.                                             LoopCpy    = FALSE;
  1146.                                         else
  1147.                                         {
  1148.                                                 // Otherwise issue error
  1149.  
  1150.                                             PrintFault(IoErr(), "\nMove ");
  1151.                                             RetVal    = FALSE;
  1152.                                             ErrCpy    = TRUE;
  1153.                                         }
  1154.                                     }
  1155.                                 }
  1156.                                 else
  1157.                                     RetVal = FALSE;
  1158.                             }
  1159.  
  1160.                                 // Free Copy buffer
  1161.  
  1162.                             FreeVec(CopyBuffer);
  1163.                         }
  1164.                         else
  1165.                         {
  1166.                                 // Issue error
  1167.  
  1168.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1169.                             RetVal    = FALSE;
  1170.                             ErrCpy    = TRUE;
  1171.                         }
  1172.  
  1173.                             // Close outfile
  1174.                     }
  1175.  
  1176.                     Close(OutFile);
  1177.                 }
  1178.                 else
  1179.                 {
  1180.                         // Issue error
  1181.  
  1182.                     PrintFault(IoErr(), "\nMove ");
  1183.                     RetVal = FALSE;
  1184.                 }
  1185.                     // Close InFile
  1186.  
  1187.                 Close(InFile);
  1188.             }
  1189.             else
  1190.             {
  1191.                     // Issue error
  1192.  
  1193.                 PrintFault(IoErr(), "\nMove ");
  1194.                 RetVal = FALSE;
  1195.             }
  1196.         }
  1197.         else
  1198.         {
  1199.                 // If RemoveFirst is not set, check again ;)
  1200.  
  1201.             if(!RemoveFirst)
  1202.             {
  1203.                 if((OutFile = Lock(DestName, ACCESS_READ)))
  1204.                 {
  1205.                     if(Examine(OutFile, FIB))
  1206.                     {
  1207.                             // If dest is a file, delete first
  1208.  
  1209.                         if(FIB->fib_DirEntryType < 0)
  1210.                         {
  1211.                                 // Get Disk block of dest file
  1212.  
  1213.                             OutKey    = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  1214.                             RemoveFirst = TRUE;
  1215.                         }
  1216.                     }
  1217.                     UnLock(OutFile);
  1218.                 }
  1219.             }
  1220.  
  1221.                 // Check if only a rename should be accomplished
  1222.  
  1223.             if(InKey != -1 && OutKey != -1)
  1224.             {
  1225.                 if(InKey == OutKey)
  1226.                     RemoveFirst = FALSE;
  1227.             }
  1228.  
  1229.                 // In Rename() mode, the destination has to be removed first
  1230.  
  1231.             if(RemoveFirst)
  1232.             {
  1233.                     // If dest file is protected check for FORCE flag
  1234.  
  1235.                 if(CopyFlags & FORCE)
  1236.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  1237.  
  1238.                 if(!DeleteFile(DestName))
  1239.                 {
  1240.                     PrintFault(IoErr(), "\nMove ");
  1241.                     RetVal = FALSE;
  1242.                 }
  1243.             }
  1244.  
  1245.             if(RetVal)
  1246.             {
  1247.                     // Now try to "rename" the file
  1248.  
  1249.                 if(!Rename(FromFile, DestName))
  1250.                 {
  1251.                     PrintFault(IoErr(), "\nMove ");
  1252.                     RetVal = FALSE;
  1253.                 }
  1254.             }
  1255.         }
  1256.  
  1257.             // Error while copying ?? -> Remove Dest file
  1258.  
  1259.         if(ErrCpy)
  1260.         {
  1261.             FPuts(OutHandle, "\nMove : Error while moving; destination removed.\n");
  1262.             DeleteFile(DestName);
  1263.         }
  1264.  
  1265.             // No Error -> Remove Source file
  1266.  
  1267.         if(RetVal && !ErrCpy)
  1268.         {
  1269.             if(!DoRename && !(RetVal = DeleteFile(FromFile)))
  1270.                 PrintFault(IoErr(), "\nMove ");
  1271.             else
  1272.             {
  1273.                     // Set bits etc. as requested
  1274.  
  1275.                 if((CopyFlags & CLONE) || (CopyFlags & DATES))
  1276.                     SetFileDate(DestName, &FIB->fib_Date);
  1277.  
  1278.                 if((CopyFlags & CLONE) || (CopyFlags & COM))
  1279.                     SetComment(DestName, FIB->fib_Comment);
  1280.  
  1281.                 if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO)))
  1282.                     SetProtection(DestName, FIB->fib_Protection);
  1283.             }
  1284.         }
  1285.  
  1286.             // Free FileInfo Block
  1287.  
  1288.         FreeVec(FIB);
  1289.     }
  1290.     else
  1291.     {
  1292.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1293.         RetVal = FALSE;
  1294.     }
  1295.  
  1296.         // Free buffer for destination name
  1297.  
  1298.     FreeVec(DestName);
  1299.  
  1300.     return(RetVal);
  1301. }
  1302.